from common import *


class NodeVisitor:  # 定义节点访问器的类
    def visit(self, node):  # 定义访问方法
        # 获取节点类型名称组成访问器方法名（子类Interpreter中方法的名称）
        method_name = 'visit_' + type(node).__name__
        '''
        # 获取访问器对象，找不到访问器时获取“generic_visit”方法对象。
        '''
        visitor = getattr(self, method_name, self.generic_visit)
        return visitor(node)  # 返回访问器访问节点的结果

    def generic_visit(self, node):  # 定义通用访问方法
        raise Exception(f'未找到“visit_{type(node).__name__}()”方法！')  # 抛出异常


class Interpreter(NodeVisitor):  # 定义解释器类（继承节点访问器类）

    GLOBAL_SCOPE = {}  # 创建符号表

    def __init__(self, parser):  # 初始化方法
        self.parser = parser  # 接收语法分析器对象

    def visit_Compound(self, node):  # 访问复合语句节点
        for child in node.children:  # 遍历复合语句节点的子节点
            self.visit(child)  # 访问子节点

    def visit_Assign(self, node):  # 访问赋值语句节点
        var_name = node.left.name  # 获取变量名称
        self.GLOBAL_SCOPE[var_name] = self.visit(node.right)  # 以变量名称为键添加变量值到符号表

    def visit_Variable(self, node):  # 访问变量节点
        var_name = node.name  # 获取变量名称
        value = self.GLOBAL_SCOPE.get(var_name)  # 获取变量值
        if value is None:  # 如果没有返回值（变量不存在）
            raise NameError(f'错误的标识符：{repr(var_name)}')  # 抛出异常
        else:  # 否则
            return value  # 返回变量值

    def visit_NoOperator(self, node):  # 访问空语句节点
        pass  # 无操作


    def visit_Program(self, node):  # 添加访问程序的方法
        self.visit(node.block)  # 访问语句块

    def visit_Block(self, node):  # 添加访问语句块的方法
        for declaration in node.declarations:  # 遍历声明列表
            self.visit(declaration)  # 访问声明
        self.visit(node.compound_statement)  # 访问复合语句

    def visit_VarDecl(self, node):  # 添加访问变量声明的方法
        pass  # 无需处理

    def visit_Type(self, node):  # 添加访问类型的方法
        pass  # 无需处理


    def visit_BinaryOperator(self, node):  # 访问二元运算符类型节点的方法
        if node.operator.value_type == PLUS:
            return self.visit(node.left) + self.visit(node.right)
        elif node.operator.value_type == MINUS:
            return self.visit(node.left) - self.visit(node.right)
        elif node.operator.value_type == MUL:
            return self.visit(node.left) * self.visit(node.right)
        elif node.operator.value_type == INTEGER_DIV:  # 如果是整数除法
            return self.visit(node.left) // self.visit(node.right)  # 返回整数除法运算结果
        elif node.operator.value_type == FLOAT_DIV:  # 如果是浮点数除法
            return self.visit(node.left) / self.visit(node.right)  # 返回浮点数除法运算结果

    # 访问数字类型节点的方法
    def visit_Num(self, node):
        return node.value

    # 访问一元运算符类型节点的方法
    def visit_UnaryOperator(self,node):
        if node.operator.value_type==PLUS:# 如果运算符类型是加号
            return +self.visit(node.expr); # 返回正的访问子节点的结果
        if node.operator.value_type==MINUS: # 如果运算符类型是减号
            return -self.visit(node.expr) # 返回负的访问子节点的结果

    def interpret(self):  # 执行解释的方法
        tree = self.parser.parser()  # 获取语法分析器分析后的树对象
        return self.visit(tree)  # 返回访问树对象的计算结果
